package com.ruoyi.life.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.exception.CustomException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.JsonUtils;
import com.ruoyi.common.core.utils.SecurityUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.life.domain.FeApartmentLeaseDetail;
import com.ruoyi.life.domain.vo.EnterpriseVo;
import com.ruoyi.life.domain.vo.FeApartmentExcelVO;
import com.ruoyi.life.domain.vo.FeApartmentVO;
import com.ruoyi.life.domain.vo.LeaseEnterpriseVO;
import com.ruoyi.life.mapper.FeApartmentLeaseDetailMapper;
import com.ruoyi.life.mapper.FeApartmentMapper;
import com.ruoyi.life.service.IFeApartmentBillService;
import com.ruoyi.life.service.IFeApartmentLeaseDetailService;
import com.ruoyi.life.service.IFeApartmentService;
import com.ruoyi.life.service.IZsCustomerService;
import com.ruoyi.life.service.manager.BillManager;
import com.ruoyi.life.service.manager.BuiRoomManager;
import com.ruoyi.omp.api.RemoteCheckMeterService;
import com.ruoyi.omp.api.domain.BuiRoom;
import com.ruoyi.omp.api.domain.FeApartmentBill;
import com.ruoyi.omp.api.domain.FeApartment;
import com.ruoyi.omp.api.domain.ZsCustomer;
import com.ruoyi.omp.api.domain.vo.RoomVO;
import com.ruoyi.omp.api.enums.LeaseStateEnum;
import com.ruoyi.system.api.LinkFileServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 公寓租赁费用Service业务层处理
 *
 * @author cjie
 * @date 2021-09-17
 */
@Service
@Slf4j
public class FeApartmentServiceImpl extends LinkFileServiceImpl implements IFeApartmentService {
    @Autowired
    private FeApartmentMapper feApartmentMapper;
/*    @Autowired
    private RemoteRoomService roomService;*/

    @Autowired
    private BuiRoomManager roomManager;

    @Autowired
    private RemoteCheckMeterService remoteEnterpriseService;

    @Autowired
    private FeApartmentLeaseDetailMapper feApartmentLeaseDetailMapper;

    @Autowired
    private BillManager billManager;

    /**
     * 查询公寓租赁费用
     *
     * @param id 公寓租赁费用ID
     * @return 公寓租赁费用
     */
    @Override
    public FeApartment selectFeApartmentById(String id) {
        return feApartmentMapper.selectFeApartmentById(id);
    }

    /**
     * 查询公寓租赁费用列表
     *
     * @param feApartment 公寓租赁费用
     * @return 公寓租赁费用
     */
    @Override
    public List<FeApartment> selectFeApartmentList(FeApartment feApartment) {
        return feApartmentMapper.selectFeApartmentList(feApartment);
    }

    /**
     * 新增公寓租赁费用
     *
     * @param feApartment 公寓租赁费用
     * @return 结果
     */
    @Override
    public int insertFeApartment(FeApartment feApartment) {
        feApartment.setId(IdUtil.getSnowflake(0, 0).nextIdStr());
        feApartment.setCreateTime(DateUtils.getNowDate());
        feApartment.setCreateBy(SecurityUtils.getUsername());
        return feApartmentMapper.insertFeApartment(feApartment);
    }

    /**
     * 修改公寓租赁费用
     *
     * @param feApartment 公寓租赁费用
     * @return 结果
     */
    @Override
    public int updateFeApartment(FeApartment feApartment) {
        feApartment.setUpdateTime(DateUtils.getNowDate());
        feApartment.setUpdateBy(SecurityUtils.getUsername());
        return feApartmentMapper.updateFeApartment(feApartment);
    }

    /**
     * 批量删除公寓租赁费用
     *
     * @param ids 需要删除的公寓租赁费用ID
     * @return 结果
     */
    @Override
    public int deleteFeApartmentByIds(String[] ids) {
        String[] res = new String[ids.length];
        for (int i = 0; i < ids.length; i++) {
            res[i] = String.valueOf(ids[i]);
        }
        deleteLinkFile(res);
        return feApartmentMapper.deleteFeApartmentByIds(ids);
    }

    /**
     * 删除公寓租赁费用信息
     *
     * @param id 公寓租赁费用ID
     * @return 结果
     */
    @Override
    public int deleteFeApartmentById(String id) {
        return feApartmentMapper.deleteFeApartmentById(id);
    }

    @Autowired
    private IFeApartmentLeaseDetailService leaseDetailService;

    @Autowired
    private IFeApartmentBillService billService;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public synchronized int addFeApartment(FeApartmentVO feApartmentVO) {
        //判断是否是新增企业
        if (StringUtils.isBlank(feApartmentVO.getEnterpriseId())) {
            //插入企业资料
            if (StringUtils.isNotBlank(feApartmentVO.getEnterprise().getEnterpriseName())) {
                //直接写入企业资料
                EnterpriseVo enterpriseVo = feApartmentVO.getEnterprise();
                enterpriseVo.setId(IdUtil.getSnowflake(0, 0).nextIdStr());
                feApartmentVO.setEnterpriseId(enterpriseVo.getId());
                feApartmentVO.setEnterpriseName(enterpriseVo.getEnterpriseName());
                addEnterprise(enterpriseVo);
            }
        }
        //设置租赁的流水账号
        String number = billManager.genLeaseNumber("LR");


        FeApartment feApartment = feApartmentVO.getFeApartment();

        feApartment.setEnterpriseId(feApartmentVO.getEnterpriseId());
        feApartment.setLeaseNum(number);
        String id = IdUtil.getSnowflake(0, 0).nextIdStr();
        feApartment.setId(id);
        feApartment.setCreateTime(DateUtils.getNowDate());
        feApartment.setCreateBy(SecurityUtils.getUsername());
        if (feApartmentVO.getFileIdList() != null) {
            linkFile(feApartmentVO.getFileIdList(), id);
        }


        //roomList
        //修改房屋状态为已租赁，并设置租赁记录id
        if (feApartmentVO.getRoomIdList() != null && feApartmentVO.getRoomIdList().size() > 0) {
            feApartmentVO.getFeApartment().setId(id);
            insertRoomLeaseState(feApartmentVO);
            // 插入lease_id
            addLeaseDetail(feApartmentVO);
        }
        // 生成首期账单
        addFirstBill(feApartmentVO);
        return feApartmentMapper.insertFeApartment(feApartment);
    }


    /**
     * 生成首张单据
     * @param feApartmentVO
     */
    private void addFirstBill(FeApartmentVO feApartmentVO){
        // 1. 按季度还是按月缴费
        // 2. 判断租赁方式
        //按月
        FeApartment feApartment = feApartmentVO.getFeApartment();
        BigDecimal rentalTotal = new BigDecimal(0);
        BigDecimal propertyTotal = new BigDecimal(0);
        BigDecimal facilityTotal = new BigDecimal(0);
        BigDecimal total = new BigDecimal(0);
        FeApartmentBill bill = new FeApartmentBill();
        if (feApartment.getLeaseModel().equals("按面积")) {
            //按面积收费 每月
            BigDecimal arePrice = feApartment.getAreaPrice();
            BigDecimal area = feApartment.getContractArea();
            BigDecimal propPrice = feApartment.getPropertyPrice();
            BigDecimal facilityPrice = feApartment.getFacilityPrice();
            long betweenDay = DateUtil.between(feApartment.getBeginTime(), feApartment.getNextPropertyDate(), DateUnit.DAY);
            rentalTotal = arePrice.multiply(area).multiply(new BigDecimal(12)).divide(new BigDecimal(365),4,RoundingMode.HALF_UP).multiply(new BigDecimal(betweenDay));
            propertyTotal = propPrice.multiply(area).multiply(new BigDecimal(12)).divide(new BigDecimal(365),4,RoundingMode.HALF_UP).multiply(new BigDecimal(betweenDay));
            total = propertyTotal.add(rentalTotal);
            //设施使用费
            if(facilityPrice != null){
                facilityTotal = facilityPrice.multiply(area).multiply(new BigDecimal(12)).divide(new BigDecimal(365),4,RoundingMode.HALF_UP).multiply(new BigDecimal(betweenDay));
                total = total.add(facilityTotal);
                bill.setFacilityFee(facilityTotal);
            }

            bill.setTotalArea(area);

        } else {
            BigDecimal rental = new BigDecimal(0);
            BigDecimal property = new BigDecimal(0);
            List<RoomVO> list = feApartmentVO.getRoomVOList();
            for (RoomVO o : list) {
                rental = rental.add(o.getAreaPrice());
                property = property.add(o.getPropertyFee());
            }
            long betweenDay = DateUtil.between(feApartment.getBeginTime(), feApartment.getNextPropertyDate(), DateUnit.DAY);
            //java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
            rentalTotal = rental.multiply(new BigDecimal(12)).divide(new BigDecimal(365),4, RoundingMode.HALF_UP).multiply(new BigDecimal(betweenDay));
            propertyTotal = property.multiply(new BigDecimal(12)).divide(new BigDecimal(365),4,RoundingMode.HALF_UP).multiply(new BigDecimal(betweenDay));
            total = propertyTotal.add(rentalTotal);
        }
        //查询等待详情
        if(StringUtils.isNotBlank(feApartmentVO.getDetails())){
            bill.setDetails(feApartmentVO.getDetails());
        }

        bill.setBillNum(billManager.genLeaseNumber("BL"));
        bill.setBeginDate(feApartment.getBeginTime());
        bill.setEndDate(DateUtil.offsetDay(feApartment.getNextPropertyDate(),-1));
        bill.setEnterpriseId(feApartmentVO.getEnterpriseId());
        bill.setEnterpriseName(feApartmentVO.getEnterpriseName());
        bill.setFeeType("2");
        bill.setFeeTypeName("公寓租金");
        bill.setRental(rentalTotal);
        bill.setPropertyFee(propertyTotal);
        bill.setReceivableAmount(total);
        bill.setPayState("0");
        bill.setBillState("0");
        bill.setRecordId(feApartment.getId());
        DateTime deadline = DateUtil.offsetDay(feApartment.getNextPropertyDate(), 15);
        bill.setDeadline(deadline);
        billService.insertFeApartmentBill(bill);
    }


    private void addLeaseDetail(FeApartmentVO feApartmentVO) {
        List<String> list = new ArrayList<>();
        //新增到租赁明细表
        feApartmentVO.getRoomVOList().stream().forEach(o -> {
            FeApartmentLeaseDetail detail = new FeApartmentLeaseDetail();
            detail.setId(IdUtil.getSnowflake(0, 0).nextIdStr());
            detail.setRoomCode(o.getRoomNum());
            detail.setRoomId(o.getId());
            detail.setEnterpriseId(feApartmentVO.getEnterpriseId());
            detail.setEnterpriseName(feApartmentVO.getEnterpriseName());
            detail.setFeProperty(o.getPropertyFee());
            detail.setRent(o.getAreaPrice());
            detail.setMargin(o.getFacilityFee());
            FeApartment ap = feApartmentVO.getFeApartment();
            detail.setLeaseId(ap.getId());
            detail.setLeaseNum(ap.getLeaseNum());
            detail.setState(1L);
            if ("1".equals(ap.getLeaseModel())) {
                detail.setType(1L);
            } else {
                detail.setType(0L);
            }
            leaseDetailService.insertFeApartmentLeaseDetail(detail);
            list.add(detail.getId());
        });
        feApartmentVO.setDetails(JsonUtils.covertList2One(list));
    }


    @Autowired
    private IZsCustomerService customerService;

    @Override
    public int addEnterprise(EnterpriseVo enterpriseVo) {
        //插入到zscustomer

        String cusId = IdUtil.getSnowflake(0, 0).nextIdStr();
        ZsCustomer zsCustomer = new ZsCustomer();
        zsCustomer.setId(cusId);
        zsCustomer.setEnterpriseName(enterpriseVo.getEnterpriseName());
        zsCustomer.setContactPhone(enterpriseVo.getContactPhone());
        zsCustomer.setEnterpriseContact(enterpriseVo.getEnterpriseContact());
        customerService.insertZsCustomer(zsCustomer);
        //插入到企业列表
        customerService.insertEnterprise(enterpriseVo, cusId);


        return 0;
    }


    /**
     * 修改房间的租赁状态
     *
     * @param
     */
    private void insertRoomLeaseState(FeApartmentVO feApartmentVO) {
        //BuiRoom buiRoom = new BuiRoom();
        feApartmentVO.getRoomVOList().forEach(roomId -> {
            BuiRoom buiRoom = roomManager.selectBuiRoomById(roomId.getId());
            buiRoom.setLeaseState(LeaseStateEnum.已租.getCode());
            buiRoom.setRecordId(feApartmentVO.getFeApartment().getId());
            roomManager.updateRoom(buiRoom);
/*           R<BuiRoom> r = roomService.getBuiRoom(roomId.getId());

            if (r.getCode() == HttpStatus.SUCCESS) {
                BuiRoom buiRoom = r.getData();
                buiRoom.setLeaseState(LeaseStateEnum.已租.getCode());
                buiRoom.setRecordId(feApartmentVO.getFeApartment().getId());
                roomService.updateRoom(buiRoom);
            }*/
        });
    }

    @Override
    public FeApartmentVO selectFeApartmentVOById(String id) {
        FeApartment feApartment = selectFeApartmentById(id);
        FeApartmentVO feApartmentVO = new FeApartmentVO();
        if(feApartment.getEnterpriseId() != null){
            feApartmentVO.setEnterpriseId(feApartment.getEnterpriseId());
        }
        feApartmentVO.setEnterpriseName(feApartment.getEnterpriseName());
        feApartmentVO.setFeApartment(feApartment);
        feApartmentVO.setRoomIdList(null);
        List<RoomVO> roomVOList = feApartmentMapper.selectRoomLesaseDetailByRecordId(id);
        feApartmentVO.setRoomVOList(roomVOList);
/*        FeApartmentLeaseDetail detail = new FeApartmentLeaseDetail();
        detail.setLeaseId(id);
        detail.setState(1L);
        List<FeApartmentLeaseDetail> leaseDetails = leaseDetailService.selectFeApartmentLeaseDetailList(detail);
        feApartmentVO.setLeaseDetailList(leaseDetails);*/
        feApartmentVO.setFileList(getFileList(id));
        return feApartmentVO;
    }

    @Override
    public int updateFeApartment1(FeApartmentVO feApartmentVO) {
        //更新 vo
        if (CollectionUtil.isNotEmpty(feApartmentVO.getRoomVOList())) {
            clearRoomLeaseState(feApartmentVO.getFeApartment().getId());
            insertRoomLeaseState(feApartmentVO);
            //feLeaseRecord.setRoomIds(JSON.toJSONString(feLeaseRecord.getRoomVOList().stream().map(RoomVO::getId).collect(Collectors.toList())));
        }
        //更新文件
        if (feApartmentVO.getFileIdList() != null) {
            linkFile(feApartmentVO.getFileIdList(), feApartmentVO.getId());
        }
        //更新 apart
        return this.updateFeApartment(feApartmentVO.getFeApartment());
    }

    /**
     * 清除设备的租赁状态
     *
     * @param recordId 租赁记录id
     */
    private void clearRoomLeaseState(String recordId) {
        BuiRoom buiRoom = new BuiRoom();
        buiRoom.setRecordId(recordId);
        List<BuiRoom> buiRoomList = roomManager.selectBuiRoomList(buiRoom);
        buiRoomList.forEach(room -> {
            room.setRecordId("");
            room.setLeaseState(LeaseStateEnum.待租.getCode());
            room.setContractArea(new BigDecimal(0));
            roomManager.updateRoom(room);
        });

/*        R<List<BuiRoom>> r = roomService.listRoom(buiRoom);
        if (r.getCode() == HttpStatus.SUCCESS) {
            r.getData().forEach(room -> {
                room.setRecordId("");
                room.setLeaseState(LeaseStateEnum.待租.getCode());
                room.setContractArea(new BigDecimal(0));
                roomService.updateRoom(room);
            });
        }*/
    }


    @Override
    public String importData(List<FeApartmentExcelVO> buiRoomVOList, String meterType) {
        if (StringUtils.isNull(buiRoomVOList) || buiRoomVOList.size() == 0) {
            throw new CustomException("导入抄表数据不能为空！");
        }
        List<FeApartmentExcelVO> sysBmTypeExcelVOS = buiRoomVOList.stream().filter(o -> StringUtils.isNotBlank(o.getEnterpriseName())).collect(Collectors.toList());

        return this.insertDataBatch(sysBmTypeExcelVOS, meterType);

    }

    @Override
    public List<LeaseEnterpriseVO> selectFeApartmentEnList() {
        return feApartmentLeaseDetailMapper.selectFeApartmentEnList();
    }

    //初始化旧数据，新数据不导入只能新增
    private String insertDataBatch(List<FeApartmentExcelVO> sysBmTypeExcelVOS, String meterType) {
        int successNum = 0;
        StringBuilder successMsg = new StringBuilder();

        //批量插入数据
        FeApartment feApartment = new FeApartment();
        for (FeApartmentExcelVO feApartmentExcelVO : sysBmTypeExcelVOS) {
            //查询企业
            BeanUtil.copyProperties(feApartmentExcelVO, feApartment);
            feApartment.setNextPropertyDate(feApartmentExcelVO.getNextPropertyDate());
            R<String> enterpriseVo = remoteEnterpriseService.getEenterpriseByName(feApartmentExcelVO.getEnterpriseName());
            if (enterpriseVo.getData() != null) {
                feApartment.setEnterpriseId(enterpriseVo.getData());
            } else {
                //插入企业
                log.info(feApartmentExcelVO.getEnterpriseName() + " 企业不存在，插入失败");
                continue;
            }
            //设置租赁的流水账号
            String number = billManager.genLeaseNumber("LR");
            feApartment.setLeaseNum(number);
            this.insertFeApartment(feApartment);

            //更新房间列表，插入详情
            BeanUtil.copyProperties(feApartment, feApartmentExcelVO);
            if (StringUtils.isNotNull(feApartmentExcelVO.getRoomNum())) {
                this.updateRoomAndInsertLeaseDetail(feApartmentExcelVO);
            }
        }


        successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + sysBmTypeExcelVOS.size() + " 条，数据如下：");
        return successMsg.toString();

    }

    private void updateRoomAndInsertLeaseDetail(FeApartmentExcelVO feApartmentExcelVO) {
        if (StringUtils.isNotNull(feApartmentExcelVO.getRoomNum())) {
            String[] rooms = feApartmentExcelVO.getRoomNum().split("/");

            String[] prices = null;
            if (StringUtils.isNotBlank(feApartmentExcelVO.getRoomAreaPrice())) {
                prices = feApartmentExcelVO.getRoomAreaPrice().split("/");
            }
            String[] propertys = null;
            if (StringUtils.isNotBlank(feApartmentExcelVO.getPropertyFee())) {
                propertys = feApartmentExcelVO.getPropertyFee().split("/");
            }

            String[] factillys = null;
            if (StringUtils.isNotBlank(feApartmentExcelVO.getFacilityFee())) {
                factillys = feApartmentExcelVO.getFacilityFee().split("/");
            }

            for (int i = 0; i < rooms.length; i++) {
                BuiRoom buiRoom = roomManager.getBuiRoomByNum(rooms[i]);
                if (buiRoom != null) {
                    buiRoom.setLeaseState(LeaseStateEnum.已租.getCode());
                    //buiRoom.setContractArea(roomId.getContractArea());
                    if (StringUtils.isNotNull(prices)) {
                        if (i < prices.length) {
                            buiRoom.setAreaPrice(new BigDecimal(prices[i]));
                        }
                    }
                    if (StringUtils.isNotNull(propertys)) {
                        if (i < propertys.length) {
                            buiRoom.setPropertyFee(new BigDecimal(propertys[i]));
                        }
                    }
                    if (StringUtils.isNotNull(factillys)) {
                        if (i < factillys.length) {
                            buiRoom.setFacilityFee(new BigDecimal(factillys[i]));
                        }
                    }
                    buiRoom.setRecordId(feApartmentExcelVO.getId());
                    roomManager.updateRoom(buiRoom);
                    //插入 租赁详情
                    FeApartmentLeaseDetail detail = new FeApartmentLeaseDetail();
                    detail.setRoomCode(buiRoom.getRoomNum());
                    detail.setRoomId(buiRoom.getId());
                    detail.setEnterpriseId(feApartmentExcelVO.getEnterpriseId());
                    detail.setEnterpriseName(feApartmentExcelVO.getEnterpriseName());
                    detail.setFeProperty(buiRoom.getPropertyFee());
                    detail.setRent(buiRoom.getAreaPrice());
                    detail.setMargin(buiRoom.getFacilityFee());
                    detail.setLeaseId(feApartmentExcelVO.getId());
                    detail.setLeaseNum(feApartmentExcelVO.getLeaseNum());
                    detail.setState(1L);
                    if ("1".equals(feApartmentExcelVO.getLeaseModel())) {
                        detail.setType(1L);
                    } else {
                        detail.setType(0L);
                    }
                    leaseDetailService.insertFeApartmentLeaseDetail(detail);

                }else{
                    log.error(rooms[i] + " 不存在");
                }


            }


        }
    }

}
